import sys
import shutil
import re
import util


# --- Utility functions ---

def ReadFile(filename):
    file = open(filename, "rt")
    try:
        lines = file.read()
    finally:
        file.close()
    return lines


def WriteFile(filename, lines):
    file = open(filename, "w")
    try:
        lines = file.write(lines)
    finally:
        file.close()
        

def InsertBefore(s_place, s_update, s_text):
    return s_text.replace(s_place, s_update + s_place)


# --- Update files in /src dir ---

def update_json_delay_js():
    """Create nested JSON.AST object with functions """

    # file to update
    s_filename = util.get_write_path("json-delay.js")
    #print(s_filename)
    
    # get the code to append to json-delay.js
    s_append = ReadFile("src/_json-delay.js")
    #print(s_append);
    
    # append the code - only if hasn't already been appended
    if not (ReadFile(s_filename).find("SetupAST") == -1):
        #print("json-delay.js already updated")
        return
        
    fileHandle = open(s_filename, 'a' )
    fileHandle.write("\n\n" + s_append)
    fileHandle.close()


def update_runtime_h():
    """Add runtime function declaration"""
    
    # get the code to add
    s_update = ReadFile("src/_runtime.h")
    
    # filename
    s_filename = "runtime.h"
    
    # Add the code before the Pseudo functions section
    s_replace_text = "  /* Pseudo functions"
    s_text = ReadFile(util.get_read_path(s_filename))
    s_text = s_text.replace(s_replace_text, s_update + s_replace_text)
    WriteFile(util.get_write_path(s_filename), s_text)


def update_runtime_cc():
    """Add runtime function body"""
    
    # 1) Add runtime function body
    
    # get the code to add
    s_update = ReadFile("src/_runtime.cc")
    
    # filename
    s_filename = "runtime.cc"
    
    # Add the code before the Pseudo functions section
    s_place = """// ----------------------------------------------------------------------------
// Implementation of Runtime"""
    s_text = ReadFile(util.get_read_path(s_filename))
    #s_text = s_text.replace(s_replace_text, s_update + s_replace_text)
    s_text = InsertBefore(s_place, s_update, s_text)

    # 2) Add the header include of the code the runtime function calls
    
    # TODO: update if replace prettyprinter.cc with json-ast.h
    #include "json-ast.h"
    s_header_update = "\n#include \"prettyprinter.h\""
    s_header_place = """
#include "runtime.h"
"""
    s_text = InsertBefore(s_header_place, s_header_update, s_text)
    
    # 3) Write the updates to runtime.cc
    
    WriteFile(util.get_write_path(s_filename), s_text)


def fix_proxy():
    """ Update the token.h file. 
        Update the TOKEN_LIST macro with new zed tokens.
        
    """
    
    s_new = """
void JsonAstBuilder::VisitVariableProxy(VariableProxy* expr) {
 TagScope tag(this, "VariableProxy");

 AttributesScope attributes(this);
 AddAttribute("name", expr->name());

 Variable* var = expr->var();
 if (var != NULL) {
     AddAttribute("mode", Variable::Mode2String(var->mode()));
     if (var->rewrite() != NULL) {
       Visit(var->rewrite());
     }
 }
}
"""

    s_old = """
void JsonAstBuilder::VisitVariableProxy(VariableProxy* expr) {
  if (expr->var()->rewrite() == NULL) {
    TagScope tag(this, "VariableProxy");
    {
      AttributesScope attributes(this);
      AddAttribute("name", expr->name());
      AddAttribute("mode", Variable::Mode2String(expr->var()->mode()));
    }
  } else {
    Visit(expr->var()->rewrite());
  }
}
"""

    # filename
    s_filename = "prettyprinter.cc"
    
    # read the file
    f = open(util.get_read_path(s_filename))
    s_file = f.read() 
    f.close()


    s_file = s_file.replace(s_old, s_new)
    
    # write the file
    f = open(util.get_write_path(s_filename), "w")
    f.write(s_file)
    f.close()


# call the main function
if __name__ == "__main__":
    print("======== lib.py should not be called directly ==========")

